#include "stdafx.h"

#include <ctype.h>
  
#include "../../../include/tinyxml/tinyxml.h"


bool TiXmlBase::condenseWhiteSpace = true;
//int TiXmlBase::m_encoding = TIXML_ENCODING_UNKNOWN;



void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_OSTREAM* stream )
{
	TIXML_STRING buffer;
	PutString( str, &buffer );
	(*stream) << buffer;
}

void TiXmlBase::PutString( const TIXML_STRING& str, TIXML_STRING* outString )
{
	int i=0;

	while( i<(int)str.length() )
	{
		unsigned char c = (unsigned char) str[i];

		if (    c == '&' 
		     && i < ( (int)str.length() - 2 )
			 && str[i+1] == '#'
			 && str[i+2] == 'x' )
		{
			// Hexadecimal character reference.
			// Pass through unchanged.
			// &#xA9;	-- copyright symbol, for example.
			//
			// The -1 is a bug fix from Rob Laveaux. It keeps
			// an overflow from happening if there is no ';'.
			// There are actually 2 ways to exit this loop -
			// while fails (error case) and break (semicolon found).
			// However, there is no mechanism (currently) for
			// this function to return an error.
			while ( i<(int)str.length()-1 )
			{
				outString->append( str.c_str() + i, 1 );
				++i;
				if ( str[i] == ';' )
					break;
			}
		}
		else if ( c == '&' )
		{
			outString->append( entity[0].str, entity[0].strLength );
			++i;
		}
		else if ( c == '<' )
		{
			outString->append( entity[1].str, entity[1].strLength );
			++i;
		}
		else if ( c == '>' )
		{
			outString->append( entity[2].str, entity[2].strLength );
			++i;
		}
		else if ( c == '\"' )
		{
			outString->append( entity[3].str, entity[3].strLength );
			++i;
		}
		else if ( c == '\'' )
		{
			outString->append( entity[4].str, entity[4].strLength );
			++i;
		}
		else if ( c < 32 )
		{
			// Easy pass at non-alpha/numeric/symbol
			// Below 32 is symbolic.
			char buf[ 32 ];
			
			#if defined(TIXML_SNPRINTF)		
				TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
			#else
				sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
			#endif		

			//*ME:	warning C4267: convert 'size_t' to 'int'
			//*ME:	Int-Cast to make compiler happy ...
			outString->append( buf, (int)strlen( buf ) );
			++i;
		}
		else
		{
			//char realc = (char) c;
			//outString->append( &realc, 1 );
			*outString += (char) c;	// somewhat more efficient function call.
			++i;
		}
	}
}


// <-- Strange class for a bug fix. Search for STL_STRING_BUG
TiXmlBase::StringToBuffer::StringToBuffer( const TIXML_STRING& str )
{
	buffer = new char[ str.length()+1 ];
	if ( buffer )
	{
		strcpy( buffer, str.c_str() );
	}
}


TiXmlBase::StringToBuffer::~StringToBuffer()
{
	delete [] buffer;
}
// End strange bug fix. -->


TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
{
	parent = 0;
	type = _type;
	firstChild = 0;
	lastChild = 0;
	prev = 0;
	next = 0;
}


TiXmlNode::~TiXmlNode()
{
	TiXmlNode* node = firstChild;
	TiXmlNode* temp = 0;

	while ( node )
	{
		temp = node;
		node = node->next;
		delete temp;
	}	
}

const TIXML_STRING TiXmlNode::GetElementTextValue_String(void)
{
	TIXML_STRING strRetValue  ;

	strRetValue.clear();

	if (type == ELEMENT)
	{
		TiXmlNode *pNode = FirstChild();

		if (pNode == NULL)
		{
			return strRetValue ;
		}

		while (pNode != NULL)
		{
			if (pNode->type == TEXT)
			{
				const char * szValue = pNode->Value();

				strRetValue += szValue;
			}

			pNode = pNode->NextSibling();
		}
	}
	 
	return strRetValue;
}

bool TiXmlNode::GetElementTextValue_Bool(void)
{
	short nValue = GetElementTextValue_Short();

	if (nValue == 0)
	{
		return false;
	}
	
	return true;
}

short TiXmlNode::GetElementTextValue_Short(void)
{
	TIXML_STRING strValue =  GetElementTextValue_String() ;

	if (strValue.IsEmpty())
	{
		return 0;
	}

	short nValue = 0; 
	  
	if (sscanf(strValue.c_str(), "%d", &nValue) != 1)
	{
		throw 0;
	}

	return nValue;
}

int TiXmlNode::GetElementTextValue_Int(void)
{
	TIXML_STRING strValue = GetElementTextValue_String() ;

	if (strValue.IsEmpty())
	{
		return 0;
	}

	int nValue = 0;
	
	if (sscanf(strValue.c_str(), "%d", &nValue) != 1)
	{
		throw 0;
	}

	return nValue;
}

long TiXmlNode::GetElementTextValue_Long(void)
{
	TIXML_STRING strValue = GetElementTextValue_String() ;

	if (strValue.IsEmpty())
	{
		return 0;
	}

	long nValue = 0;
	
	if (sscanf(strValue.c_str(), "%d", &nValue) != 1)
	{
		throw 0;
	}

	return nValue;
}
 
float TiXmlNode::GetElementTextValue_Float(void)
{
	TIXML_STRING strValue = GetElementTextValue_String() ;

	if (strValue.IsEmpty())
	{
		return 0.0f;
	}

	float fValue = 0.0f;
	
	if (sscanf(strValue.c_str(), "%f", &fValue) != 1)
	{
		throw 0;
	}

	return fValue;
}

double TiXmlNode::GetElementTextValue_Double(void)
{
	TIXML_STRING strValue = GetElementTextValue_String() ;

	if (strValue.IsEmpty())
	{
		return 0.0;
	}

	double dValue = atof(strValue.c_str());
	
	return dValue;
}

time_t TiXmlNode::GetElementTextValue_Time(void)
{
	long nValue = GetElementTextValue_Long();

	return nValue;
}

void TiXmlNode::CopyTo( TiXmlNode* target ) const
{
	target->SetValue (value.c_str() );
	target->userData = userData; 
}


void TiXmlNode::Clear()
{
	TiXmlNode* node = firstChild;
	TiXmlNode* temp = 0;

	while ( node )
	{
		temp = node;
		node = node->next;
		delete temp;
	}	

	firstChild = 0;
	lastChild = 0;
}


TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
{
	assert( node->parent == 0 || node->parent == this );
	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );

	node->parent = this;

	node->prev = lastChild;
	node->next = 0;

	if ( lastChild )
		lastChild->next = node;
	else
		firstChild = node;			// it was an empty list.

	lastChild = node;
	return node;
}


TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
{
	TiXmlNode* node = addThis.Clone();
	if ( !node )
		return 0;

	return LinkEndChild( node );
}


TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
{	
	if ( !beforeThis || beforeThis->parent != this )
		return 0;

	TiXmlNode* node = addThis.Clone();
	if ( !node )
		return 0;
	node->parent = this;

	node->next = beforeThis;
	node->prev = beforeThis->prev;
	if ( beforeThis->prev )
	{
		beforeThis->prev->next = node;
	}
	else
	{
		assert( firstChild == beforeThis );
		firstChild = node;
	}
	beforeThis->prev = node;
	return node;
}


TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
{
	if ( !afterThis || afterThis->parent != this )
		return 0;

	TiXmlNode* node = addThis.Clone();
	if ( !node )
		return 0;
	node->parent = this;

	node->prev = afterThis;
	node->next = afterThis->next;
	if ( afterThis->next )
	{
		afterThis->next->prev = node;
	}
	else
	{
		assert( lastChild == afterThis );
		lastChild = node;
	}
	afterThis->next = node;
	return node;
}


TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
{
	if ( replaceThis->parent != this )
		return 0;

	TiXmlNode* node = withThis.Clone();
	if ( !node )
		return 0;

	node->next = replaceThis->next;
	node->prev = replaceThis->prev;

	if ( replaceThis->next )
		replaceThis->next->prev = node;
	else
		lastChild = node;

	if ( replaceThis->prev )
		replaceThis->prev->next = node;
	else
		firstChild = node;

	delete replaceThis;
	node->parent = this;
	return node;
}


bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
{
	if ( removeThis->parent != this )
	{	
		assert( 0 );
		return false;
	}

	if ( removeThis->next )
		removeThis->next->prev = removeThis->prev;
	else
		lastChild = removeThis->prev;

	if ( removeThis->prev )
		removeThis->prev->next = removeThis->next;
	else
		firstChild = removeThis->next;

	delete removeThis;
	return true;
}

const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const
{
	const TiXmlNode* node;
	for ( node = firstChild; node; node = node->next )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}


TiXmlNode* TiXmlNode::FirstChild( const char * _value )
{
	TiXmlNode* node;
	for ( node = firstChild; node; node = node->next )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}

TiXmlNode * TiXmlNode::LocateNode( const char * keys )  
{
	TiXmlNode *  r = this ;

	char buff[1024] ;
	strcpy( buff, keys ) ;
#if _MFC_VER <0x0700
	char * p = strtok( buff, "/\\") ;
	while( p ){
		r = r->FirstChild( p ) ;
		if( !r ) return NULL ;
		p = strtok( NULL,  "/\\") ;
	}
#else
    char *next_stok=NULL; 
	char * p = strtok_s( buff, "/\\",&next_stok) ;
	while( p ){
		r = r->FirstChild( p ) ;
		if( !r ) return NULL ;
		p = strtok_s( NULL,  "/\\",&next_stok) ;
	}
#endif
	return r ;
}



const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const
{
	const TiXmlNode* node;
	for ( node = lastChild; node; node = node->prev )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}

TiXmlNode* TiXmlNode::LastChild( const char * _value )
{
	TiXmlNode* node;
	for ( node = lastChild; node; node = node->prev )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}

const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const
{
	if ( !previous )
	{
		return FirstChild();
	}
	else
	{
		assert( previous->parent == this );
		return previous->NextSibling();
	}
}

TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
{
	if ( !previous )
	{
		return FirstChild();
	}
	else
	{
		assert( previous->parent == this );
		return previous->NextSibling();
	}
}

const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const
{
	if ( !previous )
	{
		return FirstChild( val );
	}
	else
	{
		assert( previous->parent == this );
		return previous->NextSibling( val );
	}
}

TiXmlNode* TiXmlNode::IterateChildren( const char * val, TiXmlNode* previous )
{
	if ( !previous )
	{
		return FirstChild( val );
	}
	else
	{
		assert( previous->parent == this );
		return previous->NextSibling( val );
	}
}

const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const 
{
	const TiXmlNode* node;
	for ( node = next; node; node = node->next )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}

TiXmlNode* TiXmlNode::NextSibling( const char * _value )
{
	TiXmlNode* node;
	for ( node = next; node; node = node->next )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}

const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const
{
	const TiXmlNode* node;
	for ( node = prev; node; node = node->prev )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}

TiXmlNode* TiXmlNode::PreviousSibling( const char * _value )
{
	TiXmlNode* node;
	for ( node = prev; node; node = node->prev )
	{
		if ( strcmp( node->Value(), _value ) == 0 )
			return node;
	}
	return 0;
}

void TiXmlElement::RemoveAttribute( const char * name )
{
	TIXML_STRING str( name );
	TiXmlAttribute* node = attributeSet.Find( str );
	if ( node )
	{
		attributeSet.Remove( node );
		delete node;
	}
}

void TiXmlElement::RemoveAllAttribute(void)
{
	ClearThis();
}

const TiXmlElement* TiXmlNode::FirstChildElement() const
{
	const TiXmlNode* node;

	for (	node = FirstChild();
			node;
			node = node->NextSibling() )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}

TiXmlElement* TiXmlNode::FirstChildElement()
{
	TiXmlNode* node;

	for (	node = FirstChild();
			node;
			node = node->NextSibling() )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}

const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const
{
	const TiXmlNode* node;

	for (	node = FirstChild( _value );
			node;
			node = node->NextSibling( _value ) )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}

TiXmlElement* TiXmlNode::FirstChildElement( const char * _value )
{
	TiXmlNode* node;

	for (	node = FirstChild( _value );
			node;
			node = node->NextSibling( _value ) )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}

const TiXmlElement* TiXmlNode::NextSiblingElement() const
{
	const TiXmlNode* node;

	for (	node = NextSibling();
	node;
	node = node->NextSibling() )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}

TiXmlElement* TiXmlNode::NextSiblingElement()
{
	TiXmlNode* node;

	for (	node = NextSibling();
	node;
	node = node->NextSibling() )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}

const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const
{
	const TiXmlNode* node;

	for (	node = NextSibling( _value );
	node;
	node = node->NextSibling( _value ) )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}

TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value )
{
	TiXmlNode* node;

	for (	node = NextSibling( _value );
	node;
	node = node->NextSibling( _value ) )
	{
		if ( node->ToElement() )
			return node->ToElement();
	}
	return 0;
}


const TiXmlDocument* TiXmlNode::GetDocument() const
{
	const TiXmlNode* node;

	for( node = this; node; node = node->parent )
	{
		if ( node->ToDocument() )
			return node->ToDocument();
	}
	return 0;
}

TiXmlDocument* TiXmlNode::GetDocument()
{
	TiXmlNode* node;

	for( node = this; node; node = node->parent )
	{
		if ( node->ToDocument() )
			return node->ToDocument();
	}
	return 0;
}

TiXmlElement::TiXmlElement (const char * _value)
	: TiXmlNode( TiXmlNode::ELEMENT )
{
	firstChild = lastChild = 0;
	value = _value;
}


#ifdef TIXML_USE_STL
TiXmlElement::TiXmlElement( const std::string& _value ) 
	: TiXmlNode( TiXmlNode::ELEMENT )
{
	firstChild = lastChild = 0;
	value = _value;
}
#endif


TiXmlElement::TiXmlElement( const TiXmlElement& copy)
	: TiXmlNode( TiXmlNode::ELEMENT )
{
	firstChild = lastChild = 0;
	copy.CopyTo( this );	
}


void TiXmlElement::operator=( const TiXmlElement& base )
{
	ClearThis();
	base.CopyTo( this );
}


TiXmlElement::~TiXmlElement()
{
	ClearThis();
}


void TiXmlElement::ClearThis()
{
	Clear();
	while( attributeSet.First() )
	{
		TiXmlAttribute* node = attributeSet.First();
		attributeSet.Remove( node );
		delete node;
	}
}


const char * TiXmlElement::Attribute( const char * name ) const
{
	TIXML_STRING str( name );
	const TiXmlAttribute* node = attributeSet.Find( str );

	if ( node )
		return node->Value();

	return 0;
}


const char * TiXmlElement::Attribute( const char * name, int* i ) const
{
	const char * s = Attribute( name );
	if ( i )
	{
		if ( s )
			*i = atoi( s );
		else
			*i = 0;
	}
	return s;
}


const char * TiXmlElement::Attribute( const char * name, double* d ) const
{
	const char * s = Attribute( name );
	if ( d )
	{
		if ( s )
			*d = atof( s );
		else
			*d = 0;
	}
	return s;
}

//
//char* TiXmlElement::GetAllAttribute(CStringArray &aryName, CStringArray &aryValue)
//{
//	aryName.RemoveAll();
//	aryValue.RemoveAll();
//
//	CString strAllAttr;
//	const TiXmlAttribute* pCurrentAttr = FirstAttribute();
//	while (pCurrentAttr) {
//		CString strName(pCurrentAttr->Name());
//		CString strValue(pCurrentAttr->Value());
//		
//		aryName.Add(strName);
//		aryValue.Add(strValue);
//
//		CString strTemp;
//		strTemp.Format("%s=\"%s\" ", strName, strValue);
//		strAllAttr += strTemp;
//
//		pCurrentAttr = pCurrentAttr->Next();	
//	}
//
//	strAllAttr.TrimLeft();
//	strAllAttr.TrimRight();
//
//	return strAllAttr;
//}
//
//
//CString TiXmlElement::GetAllAttribute(CMapStringToString &mapAttr)
//{
//	mapAttr.RemoveAll();
//	CStringArray aryName;
//	CStringArray aryValue;
//
//	CString strAllAttr = GetAllAttribute(aryName, aryValue);
//	for (int i = 0 ; i < aryName.GetSize() ; i ++) {
//		mapAttr.SetAt(aryName[i], aryValue[i]);
//	}
//
//	return strAllAttr;
//}


int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const
{
	TIXML_STRING str( name );
	const TiXmlAttribute* node = attributeSet.Find( str );
	if ( !node )
		return TIXML_NO_ATTRIBUTE;

	return node->QueryIntValue( ival );
}


int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const
{
	TIXML_STRING str( name );
	const TiXmlAttribute* node = attributeSet.Find( str );
	if ( !node )
		return TIXML_NO_ATTRIBUTE;

	return node->QueryDoubleValue( dval );
}

void TiXmlElement::SetAttribute( const char * cname, const char * cvalue )
{
	TIXML_STRING _name( cname );
	TIXML_STRING _value( cvalue );

	TiXmlAttribute* node = attributeSet.Find( _name );
	if ( node )
	{
		node->SetValue( cvalue );
		return;
	}

	TiXmlAttribute* attrib = new TiXmlAttribute( cname, cvalue );
	if ( attrib )
	{
		attributeSet.Add( attrib );
	}
	else
	{
		TiXmlDocument* document = GetDocument();
		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
	}
}

void TiXmlElement::SetAttribute( const char* cname, const unsigned short cvalue )
{
	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), "%d", cvalue );
	#else
		sprintf( buf, "%d", cvalue );
	#endif
	SetAttribute( cname, buf );
}

void TiXmlElement::SetAttribute( const char* cname, const short cvalue )
{
	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), "%d", cvalue );
	#else
		sprintf( buf, "%d", cvalue );
	#endif
	SetAttribute( cname, buf );
}

void TiXmlElement::SetAttribute( const char * cname, const unsigned int cvalue )
{	
	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), "%d", cvalue );
	#else
		sprintf( buf, "%d", cvalue );
	#endif
	SetAttribute( cname, buf );
}
	
void TiXmlElement::SetAttribute( const char * cname, const int cvalue )
{	
	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), "%d", cvalue );
	#else
		sprintf( buf, "%d", cvalue );
	#endif
	SetAttribute( cname, buf );
}

void TiXmlElement::SetAttribute( const char* cname, const unsigned long cvalue )
{
	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), "%d", cvalue );
	#else
		sprintf( buf, "%d", cvalue );
	#endif
	SetAttribute( cname, buf );
}

void TiXmlElement::SetAttribute( const char* cname, const long cvalue )
{
	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), "%d", cvalue );
	#else
		sprintf( buf, "%d", cvalue );
	#endif
	SetAttribute( cname, buf );
}
 

void TiXmlElement::SetAttribute( const char* cname, const float cvalue, const int prec )
{
	char strFormat[32]; 
	sprintf(strFormat, "%%.%df", prec) ; 

	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), strFormat, cvalue );
	#else
		sprintf( buf, strFormat, cvalue );
	#endif
	SetAttribute( cname, buf );
}

void TiXmlElement::SetAttribute( const char * cname, const double cvalue, const int prec )
{	
	char strFormat[32]; 
	sprintf(strFormat, "%%.%df", prec) ; 

	char buf[256];
	memset(buf, 0, 256);
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), strFormat, cvalue );
	#else
		sprintf( buf, strFormat, cvalue );
	#endif
	SetAttribute( cname, buf );
}

#ifdef TIXML_USE_STL
void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value )
{
	TiXmlAttribute* node = attributeSet.Find( name );
	if ( node )
	{
		node->SetValue( _value );
		return;
	}

	TiXmlAttribute* attrib = new TiXmlAttribute( name, _value );
	if ( attrib )
	{
		attributeSet.Add( attrib );
	}
	else
	{
		TiXmlDocument* document = GetDocument();
		if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
	}
}

void TiXmlElement::SetAttribute( const std::string& name, const int _value )
{	
   std::ostringstream oss;
   oss << _value;
   SetAttribute( name, oss.str() );
}
#endif


void TiXmlElement::Print( FILE* cfile, int depth, TiXmlEncoding encoding ) const
{
	int i;
	for ( i=0; i<depth; i++ )
	{
		PrintToFile( cfile, "    ", encoding );
	}

	char strValue[128];
	sprintf(strValue, "<%s", value.c_str());
	PrintToFile( cfile, strValue,encoding);

	const TiXmlAttribute* attrib;
	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
	{
		PrintToFile( cfile, " ", encoding );
		attrib->Print( cfile, depth,encoding );
	}

	// There are 3 different formatting approaches:
	// 1) An element without children is printed as a <foo /> node
	// 2) An element with only a text child is printed as <foo> text </foo>
	// 3) An element with children is printed on multiple lines.
	TiXmlNode* node;
	if ( !firstChild )
	{
		PrintToFile( cfile, " />", encoding );
	}
	else if ( firstChild == lastChild && firstChild->ToText() )
	{
		PrintToFile( cfile, ">" ,  encoding );
		firstChild->Print( cfile, depth + 1, encoding );
		if (firstChild->ToText()->CDATA())
		{
			for( i=0; i<depth; ++i )
				PrintToFile( cfile, "    " , encoding);
		}
		
		char strValue[128];
		sprintf(strValue, "</%s>", value.c_str(), encoding);
		PrintToFile( cfile, strValue, encoding );
	}
	else
	{
		PrintToFile( cfile, ">", encoding );

		for ( node = firstChild; node; node=node->NextSibling() )
		{
			if ( !node->ToText() )
			{
				PrintToFile( cfile, "\n" , encoding);
			}
			node->Print( cfile, depth+1, encoding );
		}
		PrintToFile( cfile, "\n" , encoding );
		for( i=0; i<depth; ++i )
		PrintToFile( cfile, "    " , encoding);

		char strValue[128];
		sprintf(strValue, "</%s>", value.c_str());
		PrintToFile( cfile, strValue, encoding );
	}
}

void TiXmlElement::StreamOut( TIXML_OSTREAM * stream ) const
{
	(*stream) << "<" << value;

	const TiXmlAttribute* attrib;
	for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
	{	
		(*stream) << " ";
		attrib->StreamOut( stream );
	}

	// If this node has children, give it a closing tag. Else
	// make it an empty tag.
	TiXmlNode* node;
	if ( firstChild )
	{ 		
		(*stream) << ">";

		for ( node = firstChild; node; node=node->NextSibling() )
		{
			node->StreamOut( stream );
		}
		(*stream) << "</" << value << ">";
	}
	else
	{
		(*stream) << " />";
	}
}


void TiXmlElement::CopyTo( TiXmlElement* target ) const
{
	// superclass:
	TiXmlNode::CopyTo( target );

	// Element class: 
	// Clone the attributes, then clone the children.
	const TiXmlAttribute* attribute = 0;
	for(	attribute = attributeSet.First();
	attribute;
	attribute = attribute->Next() )
	{
		target->SetAttribute( attribute->Name(), attribute->Value() );
	}

	TiXmlNode* node = 0;
	for ( node = firstChild; node; node = node->NextSibling() )
	{
		target->LinkEndChild( node->Clone() );
	}
}


TiXmlNode* TiXmlElement::Clone() const
{
	TiXmlElement* clone = new TiXmlElement( Value() );
	if ( !clone )
		return 0;

	CopyTo( clone );
	return clone;
}


const char* TiXmlElement::GetText() const
{
	const TiXmlNode* child = this->FirstChild();
	if ( child ) {
		const TiXmlText* childText = child->ToText();
		if ( childText ) {
			return childText->Value();
		}
	}
	return 0;
}


TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
{
	tabsize = 4;
	useMicrosoftBOM = false;
	ClearError();
}

TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
{
	tabsize = 4;
	useMicrosoftBOM = false;
	value = documentName;
	ClearError();
}


#ifdef TIXML_USE_STL
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
{
	tabsize = 4;
	useMicrosoftBOM = false;
    value = documentName;
	ClearError();
}
#endif


TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT )
{
	copy.CopyTo( this );
}


void TiXmlDocument::operator=( const TiXmlDocument& copy )
{
	Clear();
	copy.CopyTo( this );
}

char* TiXmlDocument::GetFileName(void)
{
	StringToBuffer buf( value );

	return buf.buffer;
}

bool TiXmlDocument::LoadFile( TiXmlEncoding encoding )
{
	// See STL_STRING_BUG below.
	StringToBuffer buf( value );

	if ( buf.buffer && LoadFile( buf.buffer, encoding ) )
		return true;

	return false;
}


bool TiXmlDocument::SaveFile( TiXmlEncoding encoding) const
{
	// See STL_STRING_BUG below.
	StringToBuffer buf( value );

	if ( buf.buffer && SaveFile( buf.buffer, encoding ) )
		return true;

	return false;
}

bool TiXmlDocument::LoadFile( const char* filename, TiXmlEncoding encoding )
{
	// There was a really terrifying little bug here. The code:
	//		value = filename
	// in the STL case, cause the assignment method of the std::string to
	// be called. What is strange, is that the std::string had the same
	// address as it's c_str() method, and so bad things happen. Looks
	// like a bug in the Microsoft STL implementation.
	// See STL_STRING_BUG above.
	// Fixed with the StringToBuffer class.
	value = filename;

	// reading in binary mode so that tinyxml can normalize the EOL
	FILE* file = fopen( value.c_str (), "rb" );	

	if ( file )
	{
		bool result = LoadFile( file, encoding );
		fclose( file );
		return result;
	}
	else
	{
		printf("open error \n ");
		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
		return false;
	}
}


bool TiXmlDocument::Load( char* xmlContent, TiXmlEncoding encoding )
{
	Clear();
	location.Clear();

	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
	long length = strlen( xmlContent ) ;
 
	// Strange case, but good to handle up front.
	if ( length == 0 )
	{
		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
		return false;
	}

 	TIXML_STRING data;
	data.reserve( length );
  
	char* buf = (char*)xmlContent ;
 
 	const char* lastPos = buf;
	const char* p = buf;
 
	while( *p ) {
		assert( p < (buf+length) );
		if ( *p == 0xa ) {
			// Newline character. No special rules for this. Append all the characters
			// since the last string, and include the newline.
			data.append( lastPos, (p-lastPos+1) );	// append, include the newline
			++p;									// move past the newline
			lastPos = p;							// and point to the new buffer (may be 0)
			assert( p <= (buf+length) );
		}
		else if ( *p == 0xd ) {
			// Carriage return. Append what we have so far, then
			// handle moving forward in the buffer.
			if ( (p-lastPos) > 0 ) {
				data.append( lastPos, p-lastPos );	// do not add the CR
			}
			data += (char)0xa;						// a proper newline

			if ( *(p+1) == 0xa ) {
				// Carriage return - new line sequence
				p += 2;
				lastPos = p;
				assert( p <= (buf+length) );
			}
			else {
				// it was followed by something else...that is presumably characters again.
				++p;
				lastPos = p;
				assert( p <= (buf+length) );
			}
		}
		else {
			++p;
		}
	}
	// Handle any left over characters.
	if ( p-lastPos ) {
		data.append( lastPos, p-lastPos );
	}		
 
	Parse( data.c_str(), 0, encoding );

	if (  Error() )
        return false;
    else
		return true;
}

bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
{
	if ( !file ) 
	{
		printf("xxx \n ");
		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
		return false;
	}

	// Delete the existing data:
	Clear();
	location.Clear();

	// Get the file size, so we can pre-allocate the string. HUGE speed impact.
	long length = 0;
	fseek( file, 0, SEEK_END );
	length = ftell( file );
	fseek( file, 0, SEEK_SET );

	// Strange case, but good to handle up front.
	if ( length == 0 )
	{       printf("length == 0  \n ");
		SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
		return false;
	}

	// If we have a file, assume it is all one big XML file, and read it in.
	// The document parser may decide the document ends sooner than the entire file, however.
	TIXML_STRING data;
	data.reserve( length );

	// Subtle bug here. TinyXml did use fgets. But from the XML spec:
	// 2.11 End-of-Line Handling
	// <snip>
	// <quote>
	// ...the XML processor MUST behave as if it normalized all line breaks in external 
	// parsed entities (including the document entity) on input, before parsing, by translating 
	// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to 
	// a single #xA character.
	// </quote>
	//
	// It is not clear fgets does that, and certainly isn't clear it works cross platform. 
	// Generally, you expect fgets to translate from the convention of the OS to the c/unix
	// convention, and not work generally.

	/*
	while( fgets( buf, sizeof(buf), file ) )
	{
		data += buf;
	}
	*/

	char* buf = new char[ length+1 ];
	buf[0] = 0;

	if ( fread( buf, length, 1, file ) != 1 ) {
		SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
		printf(" fread error  \n ");
		return false;
	}

	const char* lastPos = buf;
	const char* p = buf;

	buf[length] = 0;
	while( *p ) {
		assert( p < (buf+length) );
		if ( *p == 0xa ) {
			// Newline character. No special rules for this. Append all the characters
			// since the last string, and include the newline.
			data.append( lastPos, (p-lastPos+1) );	// append, include the newline
			++p;									// move past the newline
			lastPos = p;							// and point to the new buffer (may be 0)
			assert( p <= (buf+length) );
		}
		else if ( *p == 0xd ) {
			// Carriage return. Append what we have so far, then
			// handle moving forward in the buffer.
			if ( (p-lastPos) > 0 ) {
				data.append( lastPos, p-lastPos );	// do not add the CR
			}
			data += (char)0xa;						// a proper newline

			if ( *(p+1) == 0xa ) {
				// Carriage return - new line sequence
				p += 2;
				lastPos = p;
				assert( p <= (buf+length) );
			}
			else {
				// it was followed by something else...that is presumably characters again.
				++p;
				lastPos = p;
				assert( p <= (buf+length) );
			}
		}
		else {
			++p;
		}
	}
	// Handle any left over characters.
	if ( p-lastPos ) {
		data.append( lastPos, p-lastPos );
	}		
	delete [] buf;
	buf = 0;
		
	printf(" Parse  \n ");
	Parse( data.c_str(), 0, encoding );

	if (  Error() ) {
		printf(" Error :%d %s ErrorRow(%d):Errorcol(%d)\n ", ErrorId() , ErrorDesc(), ErrorRow(), ErrorCol() );
        	return false;
	}
    	else
		return true;
}


bool TiXmlDocument::SaveFile( const char * filename , TiXmlEncoding encoding) const
{
	// The old c stuff lives on...
	FILE* fp = fopen( filename, "w" );
	if ( fp )
	{
		bool result = SaveFile( fp, encoding );
		fclose( fp );
		return result;
	}
	return false;
}


bool TiXmlDocument::SaveFile( FILE* fp , TiXmlEncoding encoding) const
{
	if ( useMicrosoftBOM ) 
	{
		const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
		const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
		const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;

		fputc( TIXML_UTF_LEAD_0, fp );
		fputc( TIXML_UTF_LEAD_1, fp );
		fputc( TIXML_UTF_LEAD_2, fp );
	}
	Print( fp, 0 , encoding);
	return true;
}


void TiXmlDocument::CopyTo( TiXmlDocument* target ) const
{
	TiXmlNode::CopyTo( target );

	target->error = error;
	target->errorDesc = errorDesc.c_str ();

	TiXmlNode* node = 0;
	for ( node = firstChild; node; node = node->NextSibling() )
	{
		target->LinkEndChild( node->Clone() );
	}	
}


TiXmlNode* TiXmlDocument::Clone() const
{
	TiXmlDocument* clone = new TiXmlDocument();
	if ( !clone )
		return 0;

	CopyTo( clone );
	return clone;
}


void TiXmlDocument::Print( FILE* cfile, int depth , TiXmlEncoding encoding ) const
{
	const TiXmlNode* node;
	for ( node=FirstChild(); node; node=node->NextSibling() )
	{
		node->Print( cfile, depth, encoding );
		PrintToFile( cfile, "\n"  , encoding);
	}
}

void TiXmlDocument::StreamOut( TIXML_OSTREAM * out ) const
{
	const TiXmlNode* node;
	for ( node=FirstChild(); node; node=node->NextSibling() )
	{
		node->StreamOut( out );

		// Special rule for streams: stop after the root element.
		// The stream in code will only read one element, so don't
		// write more than one.
		if ( node->ToElement() )
			break;
	}
}


const TiXmlAttribute* TiXmlAttribute::Next() const
{
	// We are using knowledge of the sentinel. The sentinel
	// have a value or name.
	if ( next->value.IsEmpty() && next->name.IsEmpty() )
		return 0;
	return next;
}

TiXmlAttribute* TiXmlAttribute::Next()
{
	// We are using knowledge of the sentinel. The sentinel
	// have a value or name.
	if ( next->value.IsEmpty() && next->name.IsEmpty() )
		return 0;
	return next;
}

const TiXmlAttribute* TiXmlAttribute::Previous() const
{
	// We are using knowledge of the sentinel. The sentinel
	// have a value or name.
	if ( prev->value.IsEmpty() && prev->name.IsEmpty() )
		return 0;
	return prev;
}

TiXmlAttribute* TiXmlAttribute::Previous()
{
	// We are using knowledge of the sentinel. The sentinel
	// have a value or name.
	if ( prev->value.IsEmpty() && prev->name.IsEmpty() )
		return 0;
	return prev;
}

void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TiXmlEncoding encoding ) const
{
	TIXML_STRING n, v;

	PutString( name, &n );
	PutString( value, &v );

	if (value.find ('\"') == TIXML_STRING::npos)
	{
		char strValue[128];
		sprintf(strValue, "%s=\"%s\"", n.c_str(), v.c_str());

		PrintToFile (cfile, strValue, encoding );
	}
	else
	{
		char strValue[128];
		sprintf(strValue, "%s='%s'", n.c_str(), v.c_str());

		PrintToFile (cfile, strValue , encoding);
	}
}


void TiXmlAttribute::StreamOut( TIXML_OSTREAM * stream ) const
{
	if (value.find( '\"' ) != TIXML_STRING::npos)
	{
		PutString( name, stream );
		(*stream) << "=" << "'";
		PutString( value, stream );
		(*stream) << "'";
	}
	else
	{
		PutString( name, stream );
		(*stream) << "=" << "\"";
		PutString( value, stream );
		(*stream) << "\"";
	}
}

int TiXmlAttribute::QueryIntValue( int* ival ) const
{
	if ( sscanf( value.c_str(), "%d", ival ) == 1 )
		return TIXML_SUCCESS;
	return TIXML_WRONG_TYPE;
}

int TiXmlAttribute::QueryDoubleValue( double* dval ) const
{
	if ( sscanf( value.c_str(), "%lf", dval ) == 1 )
		return TIXML_SUCCESS;
	return TIXML_WRONG_TYPE;
}

void TiXmlAttribute::SetIntValue( int _value )
{
	char buf [64];
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value);
	#else
		sprintf (buf, "%d", _value);
	#endif
	SetValue (buf);
}

void TiXmlAttribute::SetDoubleValue( double _value )
{
	char buf [256];
	#if defined(TIXML_SNPRINTF)		
		TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value);
	#else
		sprintf (buf, "%lf", _value);
	#endif
	SetValue (buf);
}

int TiXmlAttribute::IntValue() const
{
	return atoi (value.c_str ());
}

double  TiXmlAttribute::DoubleValue() const
{
	return atof (value.c_str ());
}


TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT )
{
	copy.CopyTo( this );
}


void TiXmlComment::operator=( const TiXmlComment& base )
{
	Clear();
	base.CopyTo( this );
}


void TiXmlComment::Print( FILE* cfile, int depth, TiXmlEncoding encoding  ) const
{
	for ( int i=0; i<depth; i++ )
	{
		fputs( "    ", cfile );
	}
	
	char strValue[128];
	sprintf(strValue, "<!--%s-->", value.c_str());
	PrintToFile( cfile, strValue  , encoding);
}

void TiXmlComment::StreamOut( TIXML_OSTREAM * stream ) const
{
	(*stream) << "<!--";
	//PutString( value, stream );
	(*stream) << value;
	(*stream) << "-->";
}


void TiXmlComment::CopyTo( TiXmlComment* target ) const
{
	TiXmlNode::CopyTo( target );
}


TiXmlNode* TiXmlComment::Clone() const
{
	TiXmlComment* clone = new TiXmlComment();

	if ( !clone )
		return 0;

	CopyTo( clone );
	return clone;
}


void TiXmlText::Print( FILE* cfile, int depth , TiXmlEncoding encoding ) const
{
	if ( cdata )
	{
		int i;
		PrintToFile( cfile, "\n"  , encoding);
		for ( i=0; i<depth; i++ ) {
			PrintToFile( cfile, "    "  , encoding);
		}

		PrintToFile( cfile, "<![CDATA["  , encoding);

		char strValue[128];
		sprintf(strValue, "%s", value.c_str());
		PrintToFile( cfile, strValue , encoding);	// unformatted output
		
		for ( i=0; i<depth; i++ ) {
			PrintToFile( cfile, "    " , encoding);
		}
		PrintToFile( cfile, "]]>" , encoding);
	}
	else
	{
		TIXML_STRING buffer;
		PutString( value, &buffer );

		char strValue[128];
		sprintf(strValue, "%s", buffer.c_str());
		PrintToFile( cfile, strValue , encoding);
	}
}


void TiXmlText::StreamOut( TIXML_OSTREAM * stream ) const
{
	if ( cdata )
	{
		(*stream) << "<![CDATA[" << value << "]]>";
	}
	else
	{
		PutString( value, stream );
	}
}


void TiXmlText::CopyTo( TiXmlText* target ) const
{
	TiXmlNode::CopyTo( target );
	target->cdata = cdata;
}


TiXmlNode* TiXmlText::Clone() const
{	
	TiXmlText* clone = 0;
	clone = new TiXmlText( "" );

	if ( !clone )
		return 0;

	CopyTo( clone );
	return clone;
}


TiXmlDeclaration::TiXmlDeclaration( const char * _version,
									const char * _encoding,
									const char * _standalone )
	: TiXmlNode( TiXmlNode::DECLARATION )
{
	version = _version;
	encoding = _encoding;
	standalone = _standalone;
}


#ifdef TIXML_USE_STL
TiXmlDeclaration::TiXmlDeclaration(	const std::string& _version,
									const std::string& _encoding,
									const std::string& _standalone )
	: TiXmlNode( TiXmlNode::DECLARATION )
{
	version = _version;
	encoding = _encoding;
	standalone = _standalone;
}
#endif


TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy )
	: TiXmlNode( TiXmlNode::DECLARATION )
{
	copy.CopyTo( this );	
}


void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy )
{
	Clear();
	copy.CopyTo( this );
}


void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/ , TiXmlEncoding e_encoding ) const
{
	PrintToFile (cfile, "<?xml ", e_encoding );

	if ( !version.IsEmpty() )
	{
		char strValue[128];
		sprintf(strValue, "version=\"%s\" ", version.c_str ());
		PrintToFile (cfile, strValue, e_encoding );
	}
	if ( !this->encoding.IsEmpty() )
	{
		char strValue[128];
		sprintf(strValue, "encoding=\"%s\" ", this->encoding.c_str ());
		PrintToFile (cfile, strValue , e_encoding);
	}
	if ( !standalone.IsEmpty() )
	{
		char strValue[128];
		sprintf(strValue, "standalone=\"%s\" ", standalone.c_str ());
		PrintToFile (cfile, strValue , e_encoding);
	}
	PrintToFile (cfile, "?>" , e_encoding);
}

void TiXmlDeclaration::StreamOut( TIXML_OSTREAM * stream ) const
{
	(*stream) << "<?xml ";

	if ( !version.IsEmpty() )
	{
		(*stream) << "version=\"";
		PutString( version, stream );
		(*stream) << "\" ";
	}
	if ( !encoding.IsEmpty() )
	{
		(*stream) << "encoding=\"";
		PutString( encoding, stream );
		(*stream ) << "\" ";
	}
	if ( !standalone.IsEmpty() )
	{
		(*stream) << "standalone=\"";
		PutString( standalone, stream );
		(*stream) << "\" ";
	}
	(*stream) << "?>";
}


void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const
{
	TiXmlNode::CopyTo( target );

	target->version = version;
	target->encoding = encoding;
	target->standalone = standalone;
}


TiXmlNode* TiXmlDeclaration::Clone() const
{	
	TiXmlDeclaration* clone = new TiXmlDeclaration();

	if ( !clone )
		return 0;

	CopyTo( clone );
	return clone;
}


TiXmlCommand::TiXmlCommand(	const char* _type,
							const char* _href,
							const char* _alternate,
							const char* _title,
							const char* _media	)
	: TiXmlNode( TiXmlNode::COMMAND )
{
	type = _type;
	href = _href;
	alternate = _alternate;
	title = _title;
	media = _media;
}


#ifdef TIXML_USE_STL
TiXmlCommand::TiXmlCommand(	const std::string& _type,
							const std::string& _href,
							const std::string& _alternate,
							const std::string& _title,
							const std::string& _media )
	: TiXmlNode( TiXmlNode::COMMAND )
{
	type = _type;
	href = _href;
	alternate = _alternate;
	title = _title;
	media = _media;
}
#endif


TiXmlCommand::TiXmlCommand( const TiXmlCommand& copy )
	: TiXmlNode( TiXmlNode::COMMAND )
{
	copy.CopyTo( this );	
}


void TiXmlCommand::operator=( const TiXmlCommand& copy )
{
	Clear();
	copy.CopyTo( this );
}


void TiXmlCommand::Print( FILE* cfile, int /*depth*/, TiXmlEncoding encoding  ) const
{
	PrintToFile (cfile, "<?xml-stylesheet " , encoding);

	if ( !type.IsEmpty() )
	{
		char strValue[128]; 
		sprintf(strValue, "type=\"%s\" ", type.c_str ());
		PrintToFile (cfile, strValue , encoding);
	}
	if ( !href.IsEmpty() )
	{
		char strValue[128];
		sprintf(strValue, "href=\"%s\" ", href.c_str ());
		PrintToFile (cfile, strValue , encoding);
	}
	if ( !alternate.IsEmpty() )
	{
		char strValue[128];
		sprintf(strValue, "alternate=\"%s\" ", alternate.c_str ());
		PrintToFile (cfile, strValue , encoding);
	}
	if ( !title.IsEmpty() )
	{
		char strValue[128];
		sprintf(strValue, "title=\"%s\" ", title.c_str ());
		PrintToFile (cfile, strValue , encoding);
	}
	if ( !media.IsEmpty() )
	{
		char strValue[128];
		sprintf(strValue, "media=\"%s\" ", media.c_str ());
		PrintToFile (cfile, strValue , encoding);
	}
	PrintToFile (cfile, "?>" , encoding);
}

void TiXmlCommand::StreamOut( TIXML_OSTREAM * stream ) const
{
	(*stream) << "<?xml-stylesheet ";

	if ( !type.IsEmpty() )
	{
		(*stream) << "type=\"";
		PutString( type, stream );
		(*stream) << "\" ";
	}
	if ( !href.IsEmpty() )
	{
		(*stream) << "href=\"";
		PutString( href, stream );
		(*stream ) << "\" ";
	}
	if ( !alternate.IsEmpty() )
	{
		(*stream) << "alternate=\"";
		PutString( alternate, stream );
		(*stream) << "\" ";
	}
	if ( !title.IsEmpty() )
	{
		(*stream) << "title=\"";
		PutString( title, stream );
		(*stream) << "\" ";
	}
	if ( !media.IsEmpty() )
	{
		(*stream) << "media=\"";
		PutString( media, stream );
		(*stream) << "\" ";
	}
	(*stream) << "?>";
}


void TiXmlCommand::CopyTo( TiXmlCommand* target ) const
{
	TiXmlNode::CopyTo( target );

	target->type = type;
	target->href = href;
	target->alternate = alternate;
	target->title = title;
	target->media = media;
}


TiXmlNode* TiXmlCommand::Clone() const
{	
	TiXmlCommand* clone = new TiXmlCommand();

	if ( !clone )
		return 0;

	CopyTo( clone );
	return clone;
}

void TiXmlUnknown::Print( FILE* cfile, int depth , TiXmlEncoding encoding ) const
{
	for ( int i=0; i<depth; i++ )
		PrintToFile( cfile, "    "  , encoding);
	
	char strValue[128];
	sprintf(strValue, "<%s>", value.c_str());
	PrintToFile( cfile, strValue  , encoding);
}


void TiXmlUnknown::StreamOut( TIXML_OSTREAM * stream ) const
{
	(*stream) << "<" << value << ">";		// Don't use entities here! It is unknown.
}


void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const
{
	TiXmlNode::CopyTo( target );
}


TiXmlNode* TiXmlUnknown::Clone() const
{
	TiXmlUnknown* clone = new TiXmlUnknown();

	if ( !clone )
		return 0;

	CopyTo( clone );
	return clone;
}


TiXmlAttributeSet::TiXmlAttributeSet()
{
	sentinel.next = &sentinel;
	sentinel.prev = &sentinel;
}


TiXmlAttributeSet::~TiXmlAttributeSet()
{
	assert( sentinel.next == &sentinel );
	assert( sentinel.prev == &sentinel );
}


void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
{
	assert( !Find( TIXML_STRING( addMe->Name() ) ) );	// Shouldn't be multiply adding to the set.

	addMe->next = &sentinel;
	addMe->prev = sentinel.prev;

	sentinel.prev->next = addMe;
	sentinel.prev      = addMe;
}

void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
{
	TiXmlAttribute* node;

	for( node = sentinel.next; node != &sentinel; node = node->next )
	{
		if ( node == removeMe )
		{
			node->prev->next = node->next;
			node->next->prev = node->prev;
			node->next = 0;
			node->prev = 0;
			return;
		}
	}
	assert( 0 );		// we tried to remove a non-linked attribute.
}

const TiXmlAttribute* TiXmlAttributeSet::Find( const TIXML_STRING& name ) const
{
	const TiXmlAttribute* node;

	for( node = sentinel.next; node != &sentinel; node = node->next )
	{
		if ( node->name == name )
			return node;
	}
	return 0;
}

TiXmlAttribute*	TiXmlAttributeSet::Find( const TIXML_STRING& name )
{
	TiXmlAttribute* node;

	for( node = sentinel.next; node != &sentinel; node = node->next )
	{
		if ( node->name == name )
			return node;
	}
	return 0;
}

#ifdef TIXML_USE_STL	
TIXML_ISTREAM & operator >> (TIXML_ISTREAM & in, TiXmlNode & base)
{
	TIXML_STRING tag;
	tag.reserve( 8 * 1000 );
	base.StreamIn( &in, &tag );

	base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING );
	return in;
}
#endif


TIXML_OSTREAM & operator<< (TIXML_OSTREAM & out, const TiXmlNode & base)
{
	base.StreamOut (& out);
	return out;
}


#ifdef TIXML_USE_STL	
std::string & operator<< (std::string& out, const TiXmlNode& base )
{
   std::ostringstream os_stream( std::ostringstream::out );
   base.StreamOut( &os_stream );
   
   out.append( os_stream.str() );
   return out;
}
#endif


TiXmlHandle TiXmlHandle::FirstChild() const
{
	if ( node )
	{
		TiXmlNode* child = node->FirstChild();
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const
{
	if ( node )
	{
		TiXmlNode* child = node->FirstChild( value );
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::FirstChildElement() const
{
	if ( node )
	{
		TiXmlElement* child = node->FirstChildElement();
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const
{
	if ( node )
	{
		TiXmlElement* child = node->FirstChildElement( value );
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::Child( int count ) const
{
	if ( node )
	{
		int i;
		TiXmlNode* child = node->FirstChild();
		for (	i=0;
				child && i<count;
				child = child->NextSibling(), ++i )
		{
			// nothing
		}
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const
{
	if ( node )
	{
		int i;
		TiXmlNode* child = node->FirstChild( value );
		for (	i=0;
				child && i<count;
				child = child->NextSibling( value ), ++i )
		{
			// nothing
		}
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::ChildElement( int count ) const
{
	if ( node )
	{
		int i;
		TiXmlElement* child = node->FirstChildElement();
		for (	i=0;
				child && i<count;
				child = child->NextSiblingElement(), ++i )
		{
			// nothing
		}
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}


TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const
{
	if ( node )
	{
		int i;
		TiXmlElement* child = node->FirstChildElement( value );
		for (	i=0;
				child && i<count;
				child = child->NextSiblingElement( value ), ++i )
		{
			// nothing
		}
		if ( child )
			return TiXmlHandle( child );
	}
	return TiXmlHandle( 0 );
}
